package com.paper.tiger.easy.rpc.s.client.client;

import com.paper.tiger.easy.rpc.annotation.AsyncCall;
import com.paper.tiger.easy.rpc.annotation.AyncMethod;
import com.paper.tiger.easy.rpc.core.Stub;
import com.paper.tiger.easy.rpc.s.client.common.Dove;
import com.paper.tiger.easy.rpc.s.client.common.Letter;
import com.paper.tiger.easy.rpc.s.client.common.LetterType;
import com.paper.tiger.easy.rpc.s.client.registy.common.ServiceMessageData;
import io.netty.channel.Channel;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;

/**
 * [简要描述]: 动态代理对象
 * [详细描述]: 这里完成两个事情
 * 1. 对具体的调用
 * 2. 服务通信
 *
 * @author ZouHaiBo
 * @version 1.0, 2021/5/31 10:32
 * @since JDK 1.8
 */
public class ProxyInstance implements InvocationHandler
{

    private Class clazz;

    public ProxyInstance(Class clazz)
    {
        this.clazz = clazz;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        //
        Letter letter = new Letter();

        Dove dove = new Dove();
        letter.setArgs(args);

        dove.setDoveId(UUID.randomUUID().toString().replace("-", ""));

        Stub stub = ServiceMessageData.getByInterfaceName(clazz.getName());

        if (stub == null){

            throw new RuntimeException("当前没有可调用的远程服务");
        }

        AyncMethod annotation = method.getAnnotation(AyncMethod.class);

        letter.setMethod(method.getName());
        letter.setParamsTypes(method.getParameterTypes());
        letter.setInterfaceClassName(stub.getInterfaceClass());
        letter.setImplClassName(stub.getImplClass());
        letter.setServiceId(stub.getServiceId());

        dove.setLetter(letter);
        Class<?> returnType = method.getReturnType();

        if (returnType != void.class && annotation!= null){
            throw new RuntimeException("remote invoke exception");
        }

        if (annotation != null){
            Class<? extends AsyncCall> asyncClass = annotation.callClass();
            String methodName = annotation.methodName();
            letter.setMethod(methodName);
            dove.setAsyncClass(asyncClass);
            dove.setSync(false);
        }

        if (annotation == null){
            SyncUtil.addDove(dove.getDoveId());
        }

        Channel channel = ContextManager.getInstance().channel(stub.getAppName());
        dove.setLetterType(LetterType.DOVE_REQUEST.getCode());

        if (channel == null){
            throw new RuntimeException("目标服务没有启用");
        }
        channel.writeAndFlush(dove);

        // 这里变异步为同步
        if (annotation == null){

            Dove resp = SyncUtil.getData(dove.getDoveId());

            if (resp == null)
            {
                throw new RuntimeException("remote invoke exception");
            }
            if (resp.getExceptionFlag())
            {
                Throwable e = resp.getE();
                if (e instanceof RuntimeException)
                {
                    throw resp.getE();
                }
                else
                {
                    e.printStackTrace();
                }
            }

            return resp.getResult();

        }
        return null;

    }

}
